home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac100% 1998 November
/
MAC100-1998-11.ISO.7z
/
MAC100-1998-11.ISO
/
オンラインソフト定点観測
/
ユーティリティ
/
Mops 3.2.sea
/
Mops 3.2
/
Mops ƒ
/
zModules
< prev
next >
Wrap
Text File
|
1998-06-20
|
24KB
|
989 lines
(*
This file implements relocatable modules. In installed applications on
the 68k, these became separate code segments, but on the PPC they're
just rolled into the app. In the development environment, however,
they're the same as on the 68k except that they have a separate
data area (of course), and we keep them locked all the time. This is
because it's tricky to ensure we only unlock them when it's safe,
especially with the code generator doing method calls doing ?unholdMod.
Also, we really ought to have plenty of memory in the development
environment.
Modules live in separate files, and when needed, they're loaded into
two handles (code and data areas).
The management of modules is rolled into class Module - each module
we define gets a Module object which lives in the dictionary, and
handles the housekeeping details related to the module files.
Here's the module file format:
Header:
(offs 0 ) 4 bytes date/time compiled
(offs 4 ) 4 bytes DirID of source file
(offs 8 ) 4 bytes self-relative offset to exports table
(which follows the code)
(offs 12) 4 bytes code size
(offs 16) 4 bytes self-relative offset to data start
(offs 20) 4 bytes data size
Code section
Exports table:
(offs 0 ) 4 bytes offset from header start to first cfa
(offs 4 ) 4 bytes offset to next cfa
...
(offs n ) 4 bytes -1 marker for end of exports table
Data section
Here's the format of an imported word:
n bytes header
2 bytes handler code $BD2E
2 bytes export table offset for this word
4 bytes reloc addr of module object
A call to an exported word pushes the xt of the word, then calls
enterMod, which grabs the module addr and export table offset, then
calls the module.
*)
true value CLEANMOD?
false value RELEASED?
0 value THIS_MOD
0 value LAST_MOD
0 value svCDP
0 value svDP
0 value svLatest
0 value start_CDP
0 value start_DP
string $EXP
string $CXT
string $TMP
file mod_file
forward LDFROMMOD
¥ variable SAVE_CONTEXT 8 4 * allot
(*
: UNEVAL ¥ Puts things back to normal after an EVAL"
evSvDP 0EXIT ¥ Out if we're not compiling an eval"
evSvLatest -> latest
evSvDP -> DP 0 -> evSvDP
nil?: $evCxt NIF ptr: $evCxt context 32 cmove release: $evCxt THEN
;
*)
: UNMOD ¥ Puts things back to normal after a module
¥ or stand-alone code compilation or eval"
¥ unEval
svCDP 0EXIT ¥ Out if we're not compiling a module/SA
svLatest -> latest
svCDP -> CDP svDP -> DP
0 -> svCDP 0 -> svDP 0 -> compMod
nil?: $cxt NIF ptr: $cxt context 32 cmove release: $cxt THEN
false -> SAcomp?
;
: >NXTEXP ¥ ( cfa -- ) Adds the next cfa offset to the string $exp
¥ which will become the exports table.
start_CDP - pad ! pad 4 add: $exp ;
(* COMPIMP ( ^mod -- ) compiles the dic entry for an imported word,
as defined in the construct
FROM <modName> IMPORT{ name0 name1 ... }
^mod is the data address of the module object.
For name0, say, we compile a header, then a 2-byte self-relative
offset back to the module object itself, then a 2-byte field
which is initially zero, but gets filled in when we compile the
module, and set to the offset within the module's export table
for the entry for name0.
*)
: COMPIMP { ^mod -- }
header
$ BD2E codeW, ¥ handler code for imported_h
0 codeW, ¥ space for export table offset
^mod relocCode, ¥ ptr to module
;
¥ Note: MLOCAL is still (29-7-97) not working properly, so I'll
¥ make these into Values, temporarily:
0 value thisImp
0 value thisCfa
¥ 0 value maddr
:class MODULE super{ object }
record
{ handle modHdl
uint SEG#
byte FLAGS
int RES#
int #IMP
dicaddr LASTIMP
var DicDateTime
int RELOFFS
bool INSTALL?
}
:m PRINT:
." modHdl " get: modHdl dup nilH =
IF drop ." (not loaded)"
ELSE .h ." -> " ptr: modHdl .h
THEN cr
." seg# " print: seg# cr
." flags " print: flags cr
." install? " print: install? cr
;m
:m BASE:
nil?: modHdl IF 0 EXIT THEN
nptr: modHdl ;m
:m HANDLE: get: modHdl ;m
:m EXEC_CNT: 99 ;m ¥ not used on PPC
:m SETRELEASE: ¥ ( addr -- )
modcode - put: relOffs ;m
:m SETRESID: ¥ ( resID -- )
put: res# ;m
:m INSTALL?: get: install? ;m
:m SETINSTALL: { instl? ¥ ^ST -- }
instl? put: install?
get: seg# segTable_entry -> ^ST
instl? 1 and
dup 1 ^ST creplace 1 ^ST 8 + creplace
;m
¥ KLUDGE: and UNKLUDGE: may be used when we save a dic image, to mark
¥ a module as unloaded in the saved image without really unloading it.
¥ :m KLUDGE: ¥ ( -- modHdl flags exec+locked? )
¥ get: modHdl get: flags addr: exec_cnt w@ nilH put: modHdl ;m
¥ :m UNKLUDGE: ¥ ( modHdl flags exec+locked? -- )
¥ addr: exec_cnt w! put: flags put: modHdl ;m
:m EXTNAME: { xaddr xlen ¥ len -- addr' len' }
getName: self -> len pad len cmove
xaddr pad len + xlen cmove ¥ Add extension
pad len xlen + ;m
:m BINNAME: ¥ ( -- addr len ) Returns name of binary file for module.
" .PBIN" extName: self ;m
:m TXTNAME: ¥ ( -- addr len ) Returns name of text file for module.
" .TXT" extName: self ;m
:m LOAD: { ¥ rc modstart ^ST -- } ¥ Loads if not loaded already
instld? ¥ if installed, mods are always loaded
IF
get: seg# segTable_entry -> ^ST
^ST 4+ @ nilP = IF $ dead db THEN
EXIT
THEN
nil?: modHdl 0EXIT
¥ get: res#
¥ IF 'type CODE get: res# getRes dup 0= ?error 138
¥ put: modHdl
¥ ELSE
binName: self name: mod_file 0 setVref: mod_file
openReadOnly: mod_file ?error 138
¥ ['] pause 4+ @ 0 -> pause ¥ Disable pause over read to avoid
¥ ¥ possible reentrancy
size: mod_file dup new: modHdl
lock: modHdl ¥ Maybe we need this
ptr: modHdl swap read: mod_file -> rc
¥ ['] pause 4+ ! ¥ Restore pause
unlock: modHdl ¥ Unlock before error check
close: mod_file drop rc ?error 141
base: self @ get: dicDateTime u<
IF ¥ BIN file is old version
release: modHdl 148 die
THEN
¥ THEN
moveHi: modHdl ¥ Move module hi since it gets locked
lock: modHdl
¥ now we update the ST entries for the code and data segments:
nptr: modHdl -> modstart
get: seg# segTable_entry -> ^ST
modstart ¥ code start
^ST 4+ !
modstart 12 + @ ¥ code size
^ST @ $ FF000000 and or
^ST !
modstart 16 + dup @ + ¥ data start
^ST 12 + !
modstart 20 + @ ¥ data size
^ST 8 + @ $ FF000000 and or
^ST 8 + !
¥ now we must fix the icache:
modstart dup 12 + @ fix_caches
;m
:m LOAD_FOR_EXECUTION: ( -- ptr )
instld? ¥ if installed, mods are always loaded
IF
get: seg# segTable_entry 4+ @
dup nilP = IF $ beef db THEN EXIT
THEN
nil?: modHdl IF load: self THEN
ptr: modHdl
;m
:m FINISHED_EXECUTION:
;m
:m RELEASE: { ¥ svModcode -- }
instld? ?EXIT
release: modHdl
get: seg# make_seg_absent
;m
(*
KEEP: and DROP: flag this module as needed and not needed, respectively.
The main purpose of this flagging is that if GETSPACE is called, loaded
modules will be released to make room, unless they have been flagged as
needed by KEEP:. But note that RELEASE: ignores the flag, so that we
can get rid of a module by force if necessary. This may happen if there
was a crash while the module was executing.
LOCK: is more drastic than KEEP:, since it means that this module becomes
non-relocatable. UNLOCK: reverses a LOCK:. Note that DROP: in effect does
an UNLOCK: as well.
This "locking" feature is used for ExtrasMod, which has a window, and
for the debugger and printMod, which can be entered through the back
door (via a vect or a trap). (By the way, we hope we won't have to do this
back door business anywhere else. Entering a module through the back door
is not usually a very safe thing to do.)
Locking a module can give a useful performance improvement if a module is to
be called several times in succession, since we bypass the _HLock and _Hunlock
calls if the module is marked locked.
*)
:m KEEP:
2 addr: flags cset ;m
:m DROP:
¥ get: exec_cnt NIF unlock: modHdl THEN ¥ Unlock if not executing
2 addr: flags creset ;m
:m LOCK:
load: self
;m
:m UNLOCK:
¥ false put: locked?
¥ get: exec_cnt NIF nil?: modHdl NIF unlock: modHdl THEN THEN
;m
:m KEEP?:
get: flags ;m
:m LOCKED?:
true ;m
:m ?RELEASE:
¥ keep?: self ?EXIT
¥ release: self
;m
:m #IMP: get: #imp ;m
:m getMarkerName: ¥ ( -- ) gets the marker name for the this
¥ module into the string $tmp. We use this
¥ marker to temporarily forget the part of the
¥ dic above the module declaration, so we can
¥ compile the module in that environment.
" m__" put: $tmp
getName: self add: $tmp
;m
:m GETIMPORTS: { ¥ n -- }
0 -> n
BEGIN
^base compimp 1 ++> n
& } endlist?
UNTIL
n put: #imp
latest name> put: lastimp
getMarkerName: self begin: $tmp
" marker " insert: $tmp
all: $tmp evaluate ¥ "marker m__<module name>"
release: $tmp
;m
¥ ===================================
¥ Module compilation
¥ ===================================
private
:m ExpSupers: { ^nw ¥ relocAddr -- }
BEGIN
^nw @ -> relocAddr
relocAddr 0EXIT
relocAddr 24 >>
get: seg# = ¥ look at reloc addr seg#
IF ¥ we haven't gone out-of-segment yet, so this
¥ superclass is in the module, and has to
¥ be included.
^nw @abs 2+ ¥ get to start of methods area in class info
8 FOR ¥ go through the 8 method threads
dup displace i expMethods: [self]
4+
NEXT drop
THEN
4 ++> ^nw
AGAIN ;m
public
¥ This gets called via a late bind, so must be public
:m ExpMethods: { maddr thread# -- }
BEGIN ¥ Loop thru methods in this class
maddr @ 0>=
IF ¥ We've come to the superclasses - we only
¥ have to handle these once, of course - and
¥ since the order in the export table is
¥ immaterial, we'll just do it if we're on
¥ thread zero.
thread#
NIF maddr expSupers: self
THEN EXIT
THEN
¥ Next method
maddr 14 + ( cfa of method ) >nxtExp
maddr 4+ displace -> maddr
AGAIN ;m
private
¥ &&&&&&& MLOCAL not working yet - defer to next version
¥ mlocal !exports: { ¥ thisImp thisCfa maddr -- }
:m ?!class: ¥ If this exported item is a class, we set the handler
¥ code of the imported version and add the method entry offsets
¥ to the export table.
thisCfa 2- w@ $ BC1D = 0EXIT ¥ Out if it isn't a class
$ BC2D thisImp 2- w! ¥ set handler of imported word
2 thisCfa ffa 1+ cset
thisCfa 2+ ¥ get to start of methods area in class info
8 FOR ¥ go through the 8 method threads
dup displace i expMethods: self
4+
NEXT drop ;m
:m 1export:
next: theMark link> -> thisImp
thisImp >name n>count sFind NIF 999 die THEN
-> thisCfa
thisCfa thisImp =
IF ¥ Not defined
cr thisImp .id 2 spaces 144 die
¥ "You forgot to define this exported name"
false -> cleanMod?
ELSE ¥ All OK. Put info into import definition:
thisCfa >name c@ thisImp >name c! ¥ Name flags
pos: $exp thisImp w! ¥ Export table offset
thisCfa >nxtExp ¥ Add next exp tbl entry
?!class: self ¥ More stuff if it's a class
THEN ;m
¥ :mloc !exports: ¥ { ¥ n thisImp thisCfa maddr -- }
:m !exports:
get: #imp 0= ?error 143 ¥ Module has no exported names
clear: $exp
get: lastimp set: theMark
get: #imp FOR 1export: self NEXT
-1 pad ! pad 4 add: $exp ¥ marker at end of table
¥ ;mloc
;m
(*
FixLinks: fixes up the dictionary links within the compiled module. We may
want to find words in the module at run time via FIND, but the problem is that
dic links are relative, not relocatable. This makes FIND fast, but leads
to a problem at run time when the the module is disconnected from the main
dictionary. If we didn't do anything, we wouldn't know where to start
searching from, and if the search failed, the last link would point into
outer space.
So what we do is to add a snapshot of CONTEXT to the end of the module to give
a place to start from, and to clear the lowest link on each thread to zero (which
means the end).
*)
:m FixLinks: { ¥ link prevLink -- }
#threads FOR
context i cells + -> link
BEGIN
link -> prevLink
link displace -> link
link start_CDP u<
UNTIL
0 prevLink !
NEXT
$ c0c0c0c0 code,
CDP 4+ context - code, ¥ adjustment value for context copy
context 32 codeN, ¥ add copy of Context to end of code area
;m
:m GoodCompile: { ¥ code_size data_size -- }
CDP start_CDP 8 + displ! ¥ store export table offs in header
all: $exp codeN,
¥ add export table to end
fixLinks: self ¥ fix dic links in module
CDP start_CDP - -> code_size ¥ size of code (including export table)
DP start_DP - -> data_size ¥ size of data
code_size start_CDP 12 + ! ¥ store code size in header
start_CDP code_size + ¥ where data will start
start_CDP 16 + displ! ¥ add offs to data start
data_size start_CDP 20 + ! ¥ and data size
binName: self name: mod_file ¥ Set name of binary file
create: mod_file ?error 139
'type PBIN 'type Mopp set: mod_file ¥ type and signature
start_CDP code_size write: mod_file ¥ write out code, leave err code
start_DP data_size write: mod_file or ¥ write out data, 'or' err code
close: mod_file drop
IF msg# 140 ¥ I/O error on writing bin file
ELSE
curs? -curs
cr getName: mod_file type ." saved" cr
-> curs?
THEN
;m
public
:m COMPILE: ( -- )
compMod ?error 177 ¥ Error if already compiling a module
release: self ¥ Get rid of old version, if loaded
context 32 put: $cxt ¥ save CONTEXT and other things, since
CDP -> svCDP DP -> svDP ¥ we're going to do a temporary forget
latest -> svLatest
^base -> compMod
getMarkerName: self
all: $tmp evaluate ¥ execute the marker, forgetting back to just
release: $tmp ¥ after the module declaration
svCDP -> CDP svDP -> DP
true -> cleanMod?
pushNew: loadFile
txtName: self name: topFile
CDP -> start_CDP DP -> start_DP
24 code_reserve ¥ Reserve space for header and offset to exports table.
^base -> this_mod
get: seg# -> comp_seg#
start_CDP start_DP get: seg# ldFromMod
0 -> comp_seg#
dateTime start_CDP ! ¥ Put compiled date in bin module header
getDirID: topFile start_CDP 4+ ! ¥ Also DirID of source file
drop: loadfile
0 -> this_mod
!exports: self
cleanMod?
IF goodCompile: self ¥ Everything's OK. Do final housekeeping
THEN
unmod ¥ Also releases $cxt
release: $exp ;m
¥ FIND: works like FIND, but just searches for a word in this module.
:m FIND: { s255 ¥ thrdOffs modCxt cxtOffs -- cfa T | -- s255 F }
load: self
s255 ¥ leave on stack for (find)
dup c@ 7 and 4* -> thrdOffs ¥ like what THREAD does
ptr: modHdl dup 12 + @ + 32 - -> modCxt
modCxt 4- @ -> cxtOffs
modCxt thrdOffs + displace
dup NIF ¥ thread is empty
drop false EXIT
THEN
cxtOffs -
( s255 1st-link ) (find)
;m
:m CLASSINIT:
-1 put: relOffs
dateTime put: dicDateTime
get_free_seg_pair put: seg# drop
;m
;class
(*
ENTERMOD ( xt -- ) calls a word in a module. The passed-in xt is of
the IMPORTED word (i.e. probably in the main dictionary).
Here's the format of an imported word:
n bytes header
2 bytes handler code $BD2E
2 bytes export table offset for this word
4 bytes reloc addr of module object
We arrive at imported_h in cg6 when a call to an imported word has
to be compiled. We there compile a push of the xt of the word, then
a call to enterMod, which does the main work. We put enterMod here
in zModules, since it has to do a late-bound call to the module
object, and this is much easier if it's not in the target
compilation, and is also quicker to debug.
*)
: (loadMod) { xt ¥ xt' ^mod modstart EToffs -- xt' ^mod modstart }
xt 2+ @abs -> ^mod ¥ get addr of module
xt w@x -> EToffs ¥ and export table offset
^mod load_for_execution: class_as> module
-> modstart
modstart 8 + dup @ + ¥ addr of export table
EToffs + @ ¥ module-relative offs to word's xt
modstart + -> xt' ¥ xt of word in module
xt' ^mod modstart
;
:f ENTERMOD { xt ¥ xt' ^mod modstart svMC svMD svMS moddata_start -- }
xt (loadmod) -> modstart -> ^mod -> xt'
modCode -> svMC modData -> svMD mod_seg# -> svMS
^mod 4+ w@ -> mod_seg#
modstart 16 + dup @ + ¥ data start
-> moddata_start
modstart half_displ_range + -> modcode
moddata_start half_displ_range + -> moddata
¥ now we actually call the word in the module
xt' execute
¥ now we restore everything:
svMC -> modcode svMD -> moddata svMS -> mod_seg#
^mod finished_execution: class_as> module
;f
:f (meth_in_mod) { ^obj xt modstart seg# ¥ svMC svMD svMS moddata_start -- }
modCode -> svMC modData -> svMD mod_seg# -> svMS
seg# -> mod_seg#
modstart 16 + dup @ + ¥ data start
-> moddata_start
modstart half_displ_range + -> modcode
moddata_start half_displ_range + -> moddata
¥ now we actually call the method in the module
^obj -> rY xt execute
¥ now we restore everything:
svMC -> modcode svMD -> moddata svMS -> mod_seg#
;f
:f enter_meth_in_mod { ^obj ^mod EToffs ¥ xt modstart -- }
^mod load_for_execution: class_as> module
-> modstart
modstart 8 + dup @ + ¥ addr of export table
EToffs + @ ¥ module-relative offs to word's xt
modstart + -> xt ¥ xt of method in module
^obj xt modstart ^mod 4+ w@ (meth_in_mod)
^mod finished_execution: class_as> module
;f
(* ****
:f ?enterHeldMod { ¥ moddata_start -- }
heldMod 0EXIT
heldModstart 16 + dup @ + ¥ data start
-> moddata_start
heldModstart half_displ_range + -> modcode
moddata_start half_displ_range + -> moddata
;f
:f init_in_mod { ^class ^obj ¥ xt offs
svMC svMD svMCS svMCL svMDS svMDL -- }
¥ Performs CLASSINIT: method on an object whose class is exported.
¥ The module is already held, and ^class is the in-module addr,
¥ but the base regs aren't set up. Very similar to (meth_in_mod),
¥ but we look up the method here since we need to bypass the
¥ fully general lookup.
initID ^class MFA_offset true (findm)
drop ¥ is guaranteed to find CLASSINIT: method
-> xt -> offs
offs ++> ^obj ¥ modify obj addr by offs (needed in case
¥ method is defined in any superclass
¥ but the first)
^obj xt heldmodstart heldMod 4+ w@ (meth_in_mod)
heldMod finished_execution: class_as> module
;f
**** *)
:f holdMod { xt ¥ xt' -- xt' }
xt (loadmod) -> heldModStart -> heldMod -> xt'
xt'
;f
¥ :f unHoldMod
¥ 0 -> heldMod
¥ ;f
:f LDFROMMOD { code_start data_start seg#
¥ svMC svMD svCS ^ST svModcode_comp_start svModdata_comp_start -- }
¥ Load from a module. We save and restore the current
¥ base address values, in case the load changes them.
¥ We also come here when compiling a module.
modcode -> svMC moddata -> svMD ¥ comp_seg# -> svCS
modcode_comp_start -> svModcode_comp_start
moddata_comp_start -> svModdata_comp_start
code_start half_displ_range + -> modcode
data_start half_displ_range + -> moddata
code_start -> modcode_comp_start
data_start -> moddata_comp_start
¥ seg# -> comp_seg#
seg# segTable_entry -> ^ST
code_limit CDP -
^ST @ $ FF000000 and or ^ST ! ¥ dummy max code length
code_start ^ST 4+ !
data_limit DP -
^ST 8 + @ $ FF000000 and or ^ST 8 + ! ¥ dummy max data length
data_start ^ST 12 + !
loadtop
svMC -> modcode svMD -> moddata ¥ svCS -> comp_seg#
svmodcode_comp_start -> modcode_comp_start
svmoddata_comp_start -> moddata_comp_start
;f
: SETRELEASE ¥ ( addr -- )
setRelease: [ this_mod ] ;
¥ : MLD
¥ dup load: [] ;
¥ ' mld -> modLoad
:f MOD? ¥ ( cfa -- cfa b )
dup 2- w@ $ BC0B = NIF false EXIT THEN ¥ out if not an object
dup >obj >classXt ['] module = ;f
: ?DISP { theCfa size -- } ¥ handler to release selected modules
theCfa mod? NIF drop EXIT THEN
free size < ¥ Do we still need space?
IF >obj ?release: module
ELSE drop
THEN ;
¥ PURGE forcibly releases all modules, no matter what. I'm not sure
¥ this isn't obsolete.
: (PRG) { theCfa size -- } ¥ unlock and release
theCfa mod? NIF drop EXIT THEN
>obj release: class_as> module ;
: PURGE ['] (prg) big# trav ;
: NEEDSPACE ¥ ( #bytes -- ) release modules until #bytes are available
false -> released?
freeblk drop ['] ?disp swap trav ;
: GS big# needSpace released? ;
' gs -> getSpace
: FROM ¥ ( -- ^mod sec# )
module ¥ Create module object
latest name> >obj dup -> last_mod 28 ;
: IMPORT{ ¥ ( ^mod sec# -- )
28 ?pairs getImports: []
;
: EXPORTS_CLASS
last_mod exports_class: []
;
testing?
[IF]
: QQ ." The right QQ!" cr ;
from TESTMOD import{ AA BB CC DD export_class }
: QQ ." This is the wrong QQ!!!" ; ¥ This one shouldn't!
compile: testmod
from TESTMOD2 import{ EE }
compile: testmod2
+echo
export_class EEE
: h mword hash 0 mfa_offset ;
: LOOKFOR Mword find: testmod ;
¥ endload ¥ when testing the early stuff, we bail out here
[THEN]
¥ Now that's done, the next thing we need to do is set up our HFS file
¥ access:
from PATHSMOD import{ OWP GETPATHS .PATHS }
:f OPEN_WITH_PATHS OWP ;f
compile: pathsMod
true -> use_paths?
" mops.paths" getPaths
¥ Right, we now have HFS paths, so we can access our source files in
¥ different folders.
from CALL1&LMOD import{ CallFirst CallLast (GET) (C1) (CL) }
' (get) -> get1st&last
' (C1) -> doCall1st
' (CL) -> doCallLast
compile: call1&Lmod
0 value CASE_TYPE
from zCASEMOD import{ case[ ]=> ], range]=> range], default=> ]case
select[ ]select }
compile: zCaseMod
: SELECT{ postpone select[ ; immediate
: }SELECT postpone ]select ; immediate
: IS{ postpone ]=> ; immediate
: }END postpone [ ; immediate
: DEFAULT{ postpone ] postpone default=> postpone drop ; immediate
(* ****
+echo
¥ Torture tests for CASE[ etc - something as complicated as that needs
¥ a bit of systematic testing...
: q
select[ 3 ]=> 23
[ 2 ]=> 22
[ 0 ]=> 20
[ 8 ]=> 28
default=> 999
]select ;
: qq
case[ 21 ]=> 210
[ 22 ]=> 220
[ 80 ], [ 82 ], [ 84 ], [ 86 ]=> 888
[ 30 40 range]=> 333
[ 90 ], [ 92 ], [ 170 ]=> -999
[ 90 ], [ 92 ], [ 100 150 range], [ 170 ]=> -999
[ 222 ]=> 2220
default=> 99
]case ;
: ?CHK
2dup <>
IF cr .h cr .h
true abort" check FAILED!!!" ¥ error if something doesn't
¥ give what we expect
ELSE
2drop
THEN
;
21 qq 210 ?chk
22 qq 220 ?chk
80 qq 888 ?chk
84 qq 888 ?chk
85 qq 99 ?chk 85 ?chk
35 qq 333 ?chk
92 qq -999 ?chk
120 qq -999 ?chk
170 qq -999 ?chk
222 qq 2220 ?chk
9999 qq 99 ?chk 9999 ?chk
3 q 23 ?chk
2 q 22 ?chk
8 q 28 ?chk
6 q 999 ?chk 6 ?chk
-1 q 999 ?chk -1 ?chk
9 q 999 ?chk 9 ?chk
¥ torture tests WORKED!
endload
***** *)
from pasmMod import{ :PPC_code ;PPC_code
disasm disasm_word disasm_xt
disasm_rng disasm_cnt disasm_one
set_disasm_call_range }
compile: pasmMod
$ 1000 constant kFloat ¥ OR with a #cells parm for an EXTERN
¥ to show that the parm is floating
from zCALLSMOD import{ SYSCALL KONST $>KONST LIBRARY EXTERN }
compile: zCallsMod
¥ compiling zCallsMod takes a long time, so we'll normally save
¥ the dic at this point. Therefore we now define a new RUN word.
: init2 ¥ our second stage initialization word
init1 ¥ do the 1st stage initialization
0 -> bufPtr 0 -> hiCDP ¥ for interpreting message binds
instld? NIF " mops.paths" getPaths THEN
¥ add any other special class or module initialization here.
;
: cl2 ¥ our second stage cleanup word
unmod cl1 ;
' cl2 -> abortVec
:f RUN
init2
cr ." This is Mike's interim nucleus."
cr ." Type // ppcb.ld" cr
QUIT
;f
endload
¥ More testing stuff:
+echo
:class HAHA super{ int }
callLast print:
:m BAtest:
1 2 3 . . . ;m
;class
:class SUBHAHA super{ haha }
callLast dump:
:m BAtest: -9 -8 -7 . . . ;m
;class
haha hh
subhaha ss
: q batest: hh batest: ss ;
: QQ ." QQ here. Hello. " ; ¥ This gets called from testMod
variable VB
compile: testmod2